﻿using System;
using System.Drawing;
using System.Windows.Forms;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Model;
using HighDiveEngine.Resources;

namespace HighDiveAdmin.GUI.Components
{
    /// <summary>
    /// Control that handles everything about running a contest
    /// </summary>
    public partial class RunningContestScreen : UserControl
    {
        public event MethodInvoker EventStartContest;
        public event MethodInvoker EventEndContest;
        public event MethodInvoker EventStartOffline;
        public event MethodInvoker EventCancel;
        public event DelegateVoidDoubleInt EventManualScoreEntry;
        public event MethodInvoker EventExit;
        public event DelegateVoidNullableInt EventEditDive;
        public event DelegateVoidDiveEventArgs EventSaveEditedDive;

        private RunningContestResults _resultsPanel;     //only shown when window is large enough

        #region TabAreas

        #region TabProcessing
        /// <summary>
        /// Function to be triggered when the user presses Ctrl+Tab, handles changing which tab area is active
        /// </summary>
        public void ProcessCtrlTab()
        {
            switch (TabArea)
            {
                case ActiveTabArea.Area1:
                    TabArea = ActiveTabArea.Area2;
                    break;
                case ActiveTabArea.Area2:
                    TabArea = ActiveTabArea.Area3;
                    break;
                case ActiveTabArea.Area3:
                    if (_resultsPanel != null && _resultsPanel.Visible)
                        TabArea = ActiveTabArea.Area4;
                    else
                        TabArea = ActiveTabArea.Area1;
                    break;
                case ActiveTabArea.Area4:
                    TabArea = ActiveTabArea.Area1;
                    break;
            }
        }

        /// <summary>
        /// Function to be triggered when the user presses Ctrl+Shift+Tab, handles changing which tab area is active
        /// </summary>
        public void ProcessShiftCtrlTab()
        {
            switch (TabArea)
            {
                case ActiveTabArea.Area1:
                    if (_resultsPanel != null && _resultsPanel.Visible)
                        TabArea = ActiveTabArea.Area4;
                    else
                        TabArea = ActiveTabArea.Area3;
                    break;
                case ActiveTabArea.Area2:
                    TabArea = ActiveTabArea.Area1;
                    break;
                case ActiveTabArea.Area3:
                    TabArea = ActiveTabArea.Area2;
                    break;
                case ActiveTabArea.Area4:
                    TabArea = ActiveTabArea.Area3;
                    break;
            }
        } 
        #endregion

        #region Property
        private enum ActiveTabArea
        {
            Area1,
            Area2,
            Area3,
            Area4
        }

        private ActiveTabArea _activeTabArea;

        private ActiveTabArea TabArea
        {
            get { return _activeTabArea; }
            set
            {
                _activeTabArea = value;
                switch (value)
                {
                    case ActiveTabArea.Area1:
                        _setArea1Active();
                        break;
                    case ActiveTabArea.Area2:
                        _setArea2Active();
                        break;
                    case ActiveTabArea.Area3:
                        _setArea3Active();
                        break;
                    case ActiveTabArea.Area4:
                        _setArea4Active();
                        break;
                }
            }
        } 
        #endregion

        #region SetActiveArea

        private void _setArea1Active()
        {
            _setArea1(true);
            _setArea2(false);
            _setArea3(false);
            _setArea4(false);
        }
        private void _setArea2Active()
        {
            _setArea1(false);
            _setArea2(true);
            _setArea3(false);
            _setArea4(false);
        }
        private void _setArea3Active()
        {
            _setArea1(false);
            _setArea2(false);
            _setArea3(true);
            _setArea4(false);
        }
        private void _setArea4Active()
        {
            _setArea1(false);
            _setArea2(false);
            _setArea3(false);
            _setArea4(true);
        }

        #endregion

        #region AreaSetFunctions
        private void _setArea1(bool enabled)
        {
            if (runningContestConnectionsGroupBox.Visible)
                runningContestConnectionsGroupBox.TabStop = enabled;
            if (runningContestCurrentDiveGroupBox.Visible)
                runningContestCurrentDiveGroupBox.TabStop = enabled;
            if (runningContestEndContestGroupBox.Visible)
                runningContestEndContestGroupBox.TabStop = enabled;
        }

        private void _setArea2(bool enabled)
        {
            listBoxDiveQueue.TabStop = enabled;
            if (runningContestEditDiveInQueue.Visible)
                runningContestEditDiveInQueue.TabStop = enabled;
            else if (enabled)
                listBoxDiveQueue.Focus();
        }

        private void _setArea3(bool enabled)
        {
            treeViewDiveHistory.TabStop = enabled;
            if (runningContestEditDiveInHistory.Visible)
                runningContestEditDiveInHistory.TabStop = enabled;
            else if (enabled)
                treeViewDiveHistory.Focus();
        }

        private void _setArea4(bool enabled)
        {
            if (_resultsPanel != null)
            {
                _resultsPanel.TabStop = enabled;
            }
        } 
        #endregion

        #region MouseAreaChange
        private void _runningContestSetArea1Active(object sender, EventArgs e)
        {
            if (TabArea != ActiveTabArea.Area1)
                TabArea = ActiveTabArea.Area1;
        }
        private void _runningContestSetArea2Active(object sender, EventArgs e)
        {
            if (TabArea != ActiveTabArea.Area2)
                TabArea = ActiveTabArea.Area2;
        }
        private void _runningContestSetArea3Active(object sender, EventArgs e)
        {
            if (TabArea != ActiveTabArea.Area3)
                TabArea = ActiveTabArea.Area3;
        }
        private void _runningContestSetArea4Active(object sender, EventArgs e)
        {
            if (TabArea != ActiveTabArea.Area4)
                TabArea = ActiveTabArea.Area4;
        }
        #endregion

        #endregion
        
        public RunningContestScreen()
        {
            InitializeComponent();
            runningContestConnectionsGroupBox.Visible = false;
            runningContestEndContestGroupBox.Visible = false;
            runningContestEditDiveInQueue.Visible = false;
            runningContestEditDiveInHistory.Visible = false;
            TabArea = ActiveTabArea.Area1;
        }

        #region ResizeLogic
        private void RunningContestScreen_Resize(object sender, EventArgs e)
        {
            if (Size.Width > 1162)
            {
                if (_resultsPanel == null)
                {
                    _resultsPanel = new RunningContestResults
                    {
                        Location = new Point(787, 0),
                        Height = this.Height,
                        Visible = true
                    };
                    Controls.Add(_resultsPanel);
                    _resultsPanel.Enter += _runningContestSetArea4Active;
                }
                else
                {
                    _resultsPanel.Height = this.Height;
                }
            }
            else
            {
                if (_resultsPanel != null)
                {
                    Controls.Remove(_resultsPanel);
                    _resultsPanel = null;
                }

            }
        } 
        #endregion

        #region FillFunctions
        /// <summary>
        /// Updates a judge score to the correct value in the dive history
        /// </summary>
        /// <param name="dive">Dive that has been edited</param>
        public void UpdateJudgeScoreInHistory(Dive dive)
        {
            var found = false;
            foreach (DiverTreeNode diverNode in treeViewDiveHistory.Nodes)
            {
                if (diverNode.Diver.Equals(dive.Diver))
                {
                    foreach (DiveTreeNode node in diverNode.Nodes)
                    {
                        if (node.Dive.Equals(dive))
                        {
                            node.Text = dive.ToString().Substring(dive.Diver.FirstName.Length + dive.Diver.LastName.Length + dive.Diver.StartNumber.ToString().Length + 17);
                            found = true;
                        }
                    }
                }
                if (found)
                    break;
            }
        }

        /// <summary>
        /// Fills the DiveHistory with all the dives that have been performed
        /// </summary>
        /// <param name="diveHistory">List of performed dives</param>
        public void FillDiveHistory(DiveList diveHistory)
        {
            FormMain.PopulateTreeFromDiveList(treeViewDiveHistory, diveHistory, true);
        }

        /// <summary>
        /// Fills the DiveResults with the results of the contest
        /// </summary>
        /// <param name="diveResults">List of dives sosrted by result</param>
        public void FillDiveResults(DiveList diveResults)
        {
            _resultsPanel.FillResultTree(diveResults);
        }

        /// <summary>
        /// Fills the divequeue with all the dives aboutto be performed in the contest
        /// </summary>
        /// <param name="diveQueueList">List of dives sorted by queue order</param>
        public void FillDiveQueue(DiveList diveQueueList)
        {
            listBoxDiveQueue.DataSource = null;
            listBoxDiveQueue.DataSource = diveQueueList;
        }

        /// <summary>
        /// Fills all the information about the dive about to be performed
        /// </summary>
        /// <param name="dive">Dive aboutto be performed</param>
        public void FillActiveDive(Dive dive)
        {
            runningContestCurrentDiveGroupBox.FillActiveDive(dive);
        }

        /// <summary>
        /// Fills the appropriate textbox with tthe score that has been sent in by a judge
        /// </summary>
        /// <param name="score">Score that has been sent in</param>
        public void FillJudgeScore(DiveScore score)
        {
            runningContestCurrentDiveGroupBox.FillJudgeScore(score);
        }

        /// <summary>
        /// Sets all the controls to be visible according to how many judges are in the contest
        /// </summary>
        /// <param name="judgeList">Lst of all the judges in the contest</param>
        public void FillJudgeBoxes(JudgeList judgeList)
        {
            runningContestCurrentDiveGroupBox.SetNumVisibleJudges(judgeList);
        }

        /// <summary>
        /// Hides the ConnectionPhase panel
        /// </summary>
        public void HideConnectionPhase()
        {
            runningContestConnectionsGroupBox.Visible = false;
            runningContestCurrentDiveGroupBox.Visible = true;
        }

        /// <summary>
        /// Show the connectionphase panel and sets it up with the correct judgeinformation
        /// </summary>
        /// <param name="judgeList">List of all the judges in the contest</param>
        /// <param name="adminIp"></param>
        public void ShowConnectionPhase(JudgeList judgeList, string adminIp)
        {
            runningContestConnectionsGroupBox.SetNumVisibleJudges(judgeList);
            runningContestConnectionsGroupBox.FillAdminIp(adminIp);
            runningContestConnectionsGroupBox.Visible = true;
            runningContestCurrentDiveGroupBox.Visible = false;
        }

        /// <summary>
        /// Updates all the controls associated with a judge to show his/hers connection status
        /// </summary>
        /// <param name="judge"></param>
        public void UpdateJudgeConnectionStatus(Judge judge)
        {
            if (runningContestConnectionsGroupBox.Visible)
                runningContestConnectionsGroupBox.UpdateJudgeConnectionStatus(judge);
            runningContestCurrentDiveGroupBox.UpdateJudgeConnectionStatus(judge);
        }

        /// <summary>
        /// Shows the contest completed panel
        /// </summary>
        public void ShowContestCompleted()
        {
            runningContestConnectionsGroupBox.Visible = false;
            runningContestEndContestGroupBox.Visible = true;
        }
        #endregion

        #region ButtonClickEvents
        private void runningContestConnectionsGroupBox_EventStartContest()
        {
            if (EventStartContest != null)
                EventStartContest();
            TabArea = ActiveTabArea.Area1;
        }

        private void runningContestConnectionsGroupBox_EventStartOffline()
        {
            if (EventStartOffline != null)
                EventStartOffline();
            TabArea = ActiveTabArea.Area1;
        } 
        private void runningContestConnectionsGroupBox_EventCancel()
        {
            if (EventCancel != null)
                EventCancel();
        }
        private void runningContestCurrentDiveGroupBox_EventManualScoreEntry(double score, int judgeNumber)
        {
            if (EventManualScoreEntry != null)
                EventManualScoreEntry(score, judgeNumber);
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (EventEndContest != null)
                EventEndContest();
            if (EventExit != null)
                EventExit();
        }

        private void exitToWelomeScreenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (EventEndContest != null)
                EventEndContest();
        }

        private void runningContestEndContestGroupBox_EventEndContest()
        {
            if (EventEndContest != null)
                EventEndContest();

        }

        #region EditDiveInQueue
        private void listBoxDiveQueue_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Y <= listBoxDiveQueue.SelectedIndex * 13 || e.Y >= listBoxDiveQueue.SelectedIndex * 13 + 13)
                return;
            runningContestEditDiveInQueue.FillDiveInfo((Dive)listBoxDiveQueue.Items[listBoxDiveQueue.SelectedIndex]);
            if (EventEditDive != null)
                EventEditDive(((Dive)listBoxDiveQueue.Items[listBoxDiveQueue.SelectedIndex]).DbId);
            runningContestEditDiveInQueue.BringToFront();
            groupBoxDiveQueue.Visible = false;
            runningContestEditDiveInQueue.Visible = true;
            _setArea2Active();
        }

        private void runningContestEditDiveInQueue_EventDiscard()
        {
            groupBoxDiveQueue.Visible = true;
            runningContestEditDiveInQueue.Visible = false;
        }

        private void runningContestEditDiveInQueue_EventSave(string diveCode, int height, int queueOrderNumber)
        {
            //var dive = (Dive)listBoxDiveQueue.Items[listBoxDiveQueue.SelectedIndex];
            if (EventSaveEditedDive != null)
                EventSaveEditedDive(new DiveEventArgs { DiveCode = diveCode, DiveHeight = height });
            groupBoxDiveQueue.Visible = true;
            runningContestEditDiveInQueue.Visible = false;
        } 
        private void listBoxDiveQueue_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                runningContestEditDiveInQueue.FillDiveInfo((Dive)listBoxDiveQueue.Items[listBoxDiveQueue.SelectedIndex]);
                if (EventEditDive != null)
                    EventEditDive(((Dive)listBoxDiveQueue.Items[listBoxDiveQueue.SelectedIndex]).DbId);
                runningContestEditDiveInQueue.BringToFront();
                groupBoxDiveQueue.Visible = false;
                runningContestEditDiveInQueue.Visible = true;
                _setArea2Active();
            }
        }
        #endregion

        #region EditDiveInHistory
        private void runningContestEditDiveInHistory_EventDiscardEdit()
        {
            runningContestEditDiveInHistory.Visible = false;
            treeViewDiveHistory.Visible = true;
        }

        private void runningContestEditDiveInHistory_EventSaveEdit(DiveEventArgs diveArgs)
        {
            if (EventSaveEditedDive != null)
                EventSaveEditedDive(diveArgs);
            runningContestEditDiveInHistory.Visible = false;
            treeViewDiveHistory.Visible = true;
        }

        private void treeViewDiveHistory_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.GetType() != typeof (DiveTreeNode)) return;
            if (EventEditDive != null)
                EventEditDive(((DiveTreeNode)e.Node).Dive.DbId);
            runningContestEditDiveInHistory.FillDiveToEdit(((DiveTreeNode)e.Node).Dive);
            runningContestEditDiveInHistory.Visible = true;
            treeViewDiveHistory.Visible = false;
        }
        private void treeViewDiveHistory_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (treeViewDiveHistory.SelectedNode.GetType() != typeof(DiveTreeNode)) return;
                if (EventEditDive != null)
                    EventEditDive(((DiveTreeNode)treeViewDiveHistory.SelectedNode).Dive.DbId);
                runningContestEditDiveInHistory.FillDiveToEdit(((DiveTreeNode)treeViewDiveHistory.SelectedNode).Dive);
                runningContestEditDiveInHistory.Visible = true;
                treeViewDiveHistory.Visible = false;
            }
        }

        #endregion


        #endregion
    }
}
